/**
 * 
 */
package com.qnvip.sbd.mybatis.util;

import com.qnvip.sbd.mybatis.exception.NoTableNameException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 
 * Sql 所需 Map 的构建类
 * 
 * SqlParams.N() 创建空 map，SqlParams.P(pageSize, pageNo) 初始化分页参数<br>
 * 
 * 其他方法: <br>
 * map() 返回原始 map <br>
 * add(key, value) 添加参数 <br>
 * sortBy(sortBy, sortDesc) 排序参数 <br>
 * 
 * 
 *
 */
public class SqlParams {
	
	public final static String SORT_DESC = "DESC";
	public final static String SORT_ASC = "ASC";

	protected Map<String, Object> map = null;
	private String table;
	private String where;
	
	private SqlParams() {
		this.map = new HashMap<String, Object>();
	}

	private int pageSize;
	private int pageNo;
	
	public int getPageSize() {
		return pageSize;
	}
	
	public int getPageNo() {
		return pageNo;
	}
	
	public static SqlParams N() {
		return new SqlParams();
	}
	
	/**
	 * 方便初始化数据，怎么方便怎么来
	 * 自己控制数量
	 * 
	 * @param args 传入偶数个 {@code String}
	 * @return
	 * SqlParams.N("a", "A", "b", "B") => {a=A, b=B} <br>
	 * SqlParams.N("a", "A", "b", "B", "c") => {a=A, b=B}
	 * 
	 */
	public static SqlParams N(Object... args) {
		SqlParams params = new SqlParams();
		int length = args.length;
		if (length < 2) return null;
		
		for (int i = 0, count = length / 2, index = 0; i < count; i++) {
			index = i * 2;
			params.add(String.valueOf(args[index]), args[index + 1]);
		}
		
		return params;
	}
	
	/**
	 * 添加参数
	 * @param
	 */
	public SqlParams add(String key, Object value) {
		map.put(key, value);
		return this;
	}
	
	/**
	 * 添加参数
	 * 
	 * <pre>
	 * 如果 value 是空(null, "", " ")，填充 defaultValue
	 * </pre>
	 * 
	 * @param key
	 * @param value
	 * @param defaultValue
	 * 
	 */
	public SqlParams add(String key, String value, String defaultValue) {
		return add(key, StringUtils.isBlank(value) ? defaultValue : value);
	}
	
	/**
	 * 移除项
	 * @param key
	 */
	public SqlParams remove(String key) {
		map.remove(key);
		return this;
	}
	
	/**
	 * 创建分页参数
	 * 
	 * @param pageSize 每页显示数
	 * @param pageNo 页数
	 */
	public static SqlParams P(int pageSize, int pageNo) {
		SqlParams params = new SqlParams();
		params.pageNo = pageNo;
		params.pageSize = pageSize;
		
		params.add("startRow", pageNo * pageSize);
		params.add("pageNo", pageNo);
		params.add("pageSize", pageSize);
		return params;
	}
	
	/**
	 * 设置分页参数
	 * 
	 * @param pageSize 每页显示数
	 * @param pageNo 页数
	 */
	public SqlParams setPage(int pageSize, int pageNo) {
		this.pageNo = pageNo;
		this.pageSize = pageSize;
		
		this.add("startRow", pageNo * pageSize);
		this.add("pageNo", pageNo);
		this.add("pageSize", pageSize);
		return this;
	}

	/**
	 * 排序参数
	 * @param cell 要排序的列 ifBlank id
	 * @param desc DESC|ASC ifBlank ASC
	 */
	public SqlParams sortBy(String cell, String desc) {
		return this.add("sortBy", StringUtils.defaultIfBlank(cell, "id"))
				.add("sortDesc", StringUtils.defaultIfBlank(desc, SORT_ASC));
	}
	
	private String[] join_break = {"startRow", "pageNo", "pageSize"};
	
	/**
	 * 组合查询参数 param1=value1&param2=value2...
	 */
	public String join() {
		StringBuilder builder = new StringBuilder();
		
        if (map.isEmpty()) {
            return StringUtils.EMPTY;
        }
		
		String key;
		Object value;
		for (Entry<String, Object> entry : map.entrySet()) {
			key = entry.getKey();
			value = entry.getValue();
			if (!ArrayUtils.contains(join_break, key) && value != null) {
				if (builder.length() > 0) builder.append("&");
				builder.append(key).append("=").append(value);
			}
		}
		return builder.toString();
	}

	/**
	 * 判断是否存在某个值
	 */
	public boolean has(String key) {
		return map.containsKey(key);
	}
	
	public Object get(String key) {
		return map.get(key);
	}
	
	public String getString(String key) {
		return (String) map.get(key);
	}
	
	public UpdateMap toUpdateMap() {
		if (StringUtils.isEmpty(table))
			throw new NoTableNameException("SQL查询没有表名");
		UpdateMap updateMap = new UpdateMap(table);
		if (map != null && !map.isEmpty()) {
			for (String key : map.keySet()) {
				updateMap.addWhere(key, String.valueOf(map.get(key)));
			}
		}
		return updateMap;
	}
	
	public Map<String, Object> map() {
		return map;
	}
	
	public String getTable() {
		return table;
	}

	public SqlParams setTable(String table) {
		this.table = table;
		return this;
	}

	public String getWhere() {
		return where;
	}

	public void setWhere(String where) {
		this.where = where;
	}
}
